package exsun.jt808.data.util.parse;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

public class BitOperator {
	public static final String string_encoding = "GBK";

	public static final Charset string_charset = Charset.forName(string_encoding);

	/**
	 * 把一个整形该为byte
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte integerTo1Byte(int value) {
		return (byte) (value & 0xFF);
	}

	/**
	 * 把一个整形该为1位的byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] integerTo1Bytes(int value) {
		byte[] result = new byte[1];
		result[0] = (byte) (value & 0xFF);
		return result;
	}

	/**
	 * 把一个整形改为2位的byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] integerTo2Bytes(int value) {
		byte[] result = new byte[2];
		result[0] = (byte) ((value >>> 8) & 0xFF);
		result[1] = (byte) (value & 0xFF);
		return result;
	}

	/**
	 * 把一个整形改为3位的byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] integerTo3Bytes(int value) {
		byte[] result = new byte[3];
		result[0] = (byte) ((value >>> 16) & 0xFF);
		result[1] = (byte) ((value >>> 8) & 0xFF);
		result[2] = (byte) (value & 0xFF);
		return result;
	}

	/**
	 * 把一个整形改为4位的byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] integerTo4Bytes(int value) {
		byte[] result = new byte[4];
		result[0] = (byte) ((value >>> 24) & 0xFF);
		result[1] = (byte) ((value >>> 16) & 0xFF);
		result[2] = (byte) ((value >>> 8) & 0xFF);
		result[3] = (byte) (value & 0xFF);
		return result;
	}

	/**
	 * 把byte[]转化位整形,通常为指令用
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static int byteToInteger(byte[] value) {
		int result;
		if (value.length == 1) {
			result = oneByteToInteger(value[0]);
		} else if (value.length == 2) {
			result = twoBytesToInteger(value);
		} else if (value.length == 3) {
			result = threeBytesToInteger(value);
		} else if (value.length == 4) {
			result = fourBytesToInteger(value);
		} else {
			result = fourBytesToInteger(value);
		}
		return result;
	}

	/**
	 * 把一个byte转化位整形,通常为指令用
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static int oneByteToInteger(byte value) {
		return (int) value & 0xFF;
	}

	/**
	 * 把一个2位的数组转化位整形
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static int twoBytesToInteger(byte[] value) {
		// if (value.length < 2) {
		// throw new Exception("Byte array too short!");
		// }
		int temp0 = value[0] & 0xFF;
		int temp1 = value[1] & 0xFF;
		return ((temp0 << 8) + temp1);
	}

	/**
	 * 把一个3位的数组转化位整形
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static int threeBytesToInteger(byte[] value) {
		int temp0 = value[0] & 0xFF;
		int temp1 = value[1] & 0xFF;
		int temp2 = value[2] & 0xFF;
		return ((temp0 << 16) + (temp1 << 8) + temp2);
	}

	/**
	 * 把一个4位的数组转化位整形,通常为指令用
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static int fourBytesToInteger(byte[] value) {
		// if (value.length < 4) {
		// throw new Exception("Byte array too short!");
		// }
		int temp0 = value[0] & 0xFF;
		int temp1 = value[1] & 0xFF;
		int temp2 = value[2] & 0xFF;
		int temp3 = value[3] & 0xFF;
		return ((temp0 << 24) + (temp1 << 16) + (temp2 << 8) + temp3);
	}

	/**
	 * 把一个4位的数组转化位整形
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static long fourBytesToLong(byte[] value) throws Exception {
		// if (value.length < 4) {
		// throw new Exception("Byte array too short!");
		// }
		int temp0 = value[0] & 0xFF;
		int temp1 = value[1] & 0xFF;
		int temp2 = value[2] & 0xFF;
		int temp3 = value[3] & 0xFF;
		return (((long) temp0 << 24) + (temp1 << 16) + (temp2 << 8) + temp3);
	}

	/**
	 * 把一个4位的数组转化位长整形
	 */
	public static long fourBytesToLong(byte[] data, int startIndex) {
		try {
			byte[] tmp = new byte[4];
			System.arraycopy(data, startIndex, tmp, 0, 4);
			return fourBytesToLong(tmp);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * byte[8] 转long
	 * 
	 * @param value
	 * @return
	 */
	public static long bytesToLong(byte[] value) {
		return ((((long) value[0] & 0xff) << 56) | (((long) value[1] & 0xff) << 48)
				| (((long) value[2] & 0xff) << 40) | (((long) value[3] & 0xff) << 32)
				| (((long) value[4] & 0xff) << 24) | (((long) value[5] & 0xff) << 16)
				| (((long) value[6] & 0xff) << 8) | (((long) value[7] & 0xff) << 0));
	}

	/**
	 * byte[] 转long
	 * 
	 * @param value
	 *            原始值
	 * @param startIndex
	 *            原始值开始拷贝索引
	 * @param length
	 *            目标数组长度
	 * @return
	 */
	public static long bytesToLong(byte[] value, int startIndex, int length) {
		byte[] src = new byte[length];
		System.arraycopy(value, startIndex, src, 0, length);
		return bytesToLong(src);
	}

	/**
	 * 把一个长整形改为byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] longToBytes(long value) {
		return longToBytes(value, 8);
	}

	/**
	 * 把一个长整形改为byte数组
	 * 
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static byte[] longToBytes(long value, int len) {
		byte[] result = new byte[len];
		int temp;
		for (int i = 0; i < len; i++) {
			temp = (len - 1 - i) * 8;
			if (temp == 0) {
				result[i] += (value & 0x0ff);
			} else {
				result[i] += (value >>> temp) & 0x0ff;
			}
		}
		return result;
	}

	/**
	 * 得到一个消息ID
	 * 
	 * @return
	 * @throws Exception
	 */
	public static byte[] generateTransactionID() throws Exception {
		byte[] id = new byte[16];
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 0, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 2, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 4, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 6, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 8, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 10, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 12, 2);
		System.arraycopy(integerTo2Bytes((int) (Math.random() * 65536)), 0, id, 14, 2);
		return id;
	}

	/**
	 * 把IP拆分位int数组
	 * 
	 * @param ip
	 * @return
	 * @throws Exception
	 */
	public static int[] getIntIPValue(String ip) throws Exception {
		String[] sip = ip.split("[.]");
		// if (sip.length != 4) {
		// throw new Exception("error IPAddress");
		// }
		int[] intIP = { Integer.parseInt(sip[0]), Integer.parseInt(sip[1]),
				Integer.parseInt(sip[2]), Integer.parseInt(sip[3]) };
		return intIP;
	}

	/**
	 * 把byte类型IP地址转化位字符串
	 * 
	 * @param address
	 * @return
	 * @throws Exception
	 */
	public static String getStringIPValue(byte[] address) throws Exception {
		int first = oneByteToInteger(address[0]);
		int second = oneByteToInteger(address[1]);
		int third = oneByteToInteger(address[2]);
		int fourth = oneByteToInteger(address[3]);

		return first + "." + second + "." + third + "." + fourth;
	}

	/**
	 * 合并字节数组
	 * 
	 * @param first
	 * @param rest
	 * @return
	 */
	public static byte[] concatAll(byte[] first, byte[]... rest) {
		int totalLength = first.length;
		for (byte[] array : rest) {
			if (array != null) {
				totalLength += array.length;
			}
		}
		byte[] result = Arrays.copyOf(first, totalLength);
		int offset = first.length;
		for (byte[] array : rest) {
			if (array != null) {
				System.arraycopy(array, 0, result, offset, array.length);
				offset += array.length;
			}
		}
		return result;
	}

	/**
	 * 合并字节数组
	 * 
	 * @param rest
	 * @return
	 */
	public static byte[] concatAll(List<byte[]> rest) {
		int totalLength = 0;
		for (byte[] array : rest) {
			if (array != null) {
				totalLength += array.length;
			}
		}
		byte[] result = new byte[totalLength];
		int offset = 0;
		for (byte[] array : rest) {
			if (array != null) {
				System.arraycopy(array, 0, result, offset, array.length);
				offset += array.length;
			}
		}
		return result;
	}

	public static float byte2Float(byte[] bs) {
		return Float.intBitsToFloat((((bs[3] & 0xFF) << 24) + ((bs[2] & 0xFF) << 16)
				+ ((bs[1] & 0xFF) << 8) + (bs[0] & 0xFF)));
	}

	public static float byteBE2Float(byte[] bytes) {
		int l;
		l = bytes[0];
		l &= 0xff;
		l |= ((long) bytes[1] << 8);
		l &= 0xffff;
		l |= ((long) bytes[2] << 16);
		l &= 0xffffff;
		l |= ((long) bytes[3] << 24);
		return Float.intBitsToFloat(l);
	}

	public static int getCheckSum4JT808(byte[] bs, int start, int end) {
		if (start < 0 || end > bs.length)
			throw new ArrayIndexOutOfBoundsException(
					"getCheckSum4JT808 error : index out of bounds(start=" + start + ",end=" + end
							+ ",bytes length=" + bs.length + ")");
		int cs = 0;
		for (int i = start; i < end; i++) {
			cs ^= bs[i];
		}
		return cs;
	}

	public static int getBitRange(int number, int start, int end) {
		if (start < 0)
			throw new IndexOutOfBoundsException("min index is 0,but start = " + start);
		if (end >= Integer.SIZE)
			throw new IndexOutOfBoundsException("max index is " + (Integer.SIZE - 1)
					+ ",but end = " + end);

		return (number << Integer.SIZE - (end + 1)) >>> Integer.SIZE - (end - start + 1);
	}

	public static int getBitAt(int number, int index) {
		if (index < 0)
			throw new IndexOutOfBoundsException("min index is 0,but " + index);
		if (index >= Integer.SIZE)
			throw new IndexOutOfBoundsException("max index is " + (Integer.SIZE - 1) + ",but "
					+ index);

		return ((1 << index) & number) >> index;
	}

	public static int getBitAtS(int number, int index) {
		String s = Integer.toBinaryString(number);
		return Integer.parseInt(s.charAt(index) + "");
	}

	@Deprecated
	public static int getBitRangeS(int number, int start, int end) {
		String s = Integer.toBinaryString(number);
		StringBuilder sb = new StringBuilder(s);
		while (sb.length() < Integer.SIZE) {
			sb.insert(0, "0");
		}
		String tmp = sb.reverse().substring(start, end + 1);
		sb = new StringBuilder(tmp);
		return Integer.parseInt(sb.reverse().toString(), 2);
	}

	/**
	 * 汉字，字符串转字节数组
	 * 
	 * @param value
	 *            汉字，字符串
	 * @return byte[]
	 */
	public static byte[] stringToBytes(String value) {
		return value.getBytes(string_charset);
	}

	/**
	 * 汉字，字符串转定长字节数组
	 * 
	 * @param value
	 *            汉字，字符串
	 * @param length
	 *            字节数组长度
	 * @return byte[]
	 */
	public static byte[] stringToOctetBytes(String value, int length) {
		byte[] src = value.getBytes(string_charset);
		byte[] tmp = new byte[length];
		System.arraycopy(src, 0, tmp, 0, src.length);
		return tmp;
	}

	public static String stringToHexString(String src, int byteSize) {
		if (src == null || src.equals("")) {
			return null;
		}
		StringBuilder stringBuilder = new StringBuilder();
		String hv = "00000000" + Integer.toHexString(Integer.parseInt(src));
		stringBuilder.append(hv.substring(hv.length() - byteSize * 2));
		return stringBuilder.toString();
	}

	public static void main(String[] args) {


		byte[] vehs = stringToBytes("鄂AFZ662");
		// 4 294 967 295 BYTE
		byte[] b = longToBytes(114294967295L);
		long c = BitOperator.bytesToLong(b);
		System.out.println(c);
	}

	public static String intToHex(int n, int len) {
		String nHex = Integer.toHexString(n);
		return padLeft(nHex, len, '0').toUpperCase();
	}

	public static String padLeft(String src, int len, char ch) {
		int diff = len - src.length();
		if (diff <= 0) {
			return src;
		}

		char[] charr = new char[len];
		System.arraycopy(src.toCharArray(), 0, charr, diff, src.length());
		for (int i = 0; i < diff; i++) {
			charr[i] = ch;
		}
		return new String(charr);
	}

	public static String padRight(String src, int len, char ch) {
		int diff = len - src.length();
		if (diff <= 0) {
			return src;
		}

		char[] charr = new char[len];
		System.arraycopy(src.toCharArray(), 0, charr, 0, src.length());

		return new String(charr);
	}
	//字节长度填充
	public static byte[] padRight(byte[] src, int len) {
		int diff = len - src.length;
		if (diff <= 0) {
			return src;
		}
		byte[] charr = new byte[len];
		System.arraycopy(src, 0, charr, 0, src.length);

		return charr;
	}
	/**
	 * 将十六进制的字符串转化为字节数组
	 * @param hexvalue
	 * @return
	 */
	public  static  byte[] hexstringToBytes(String hexvalue)
	{
		byte[] bs = new byte[hexvalue.length() / 2];
		for (int i = 0; i < hexvalue.length() / 2; i++)
		{
			bs[i] = (byte)(hexToInt(hexvalue.substring(i * 2, i * 2 + 2)));
		}

		return bs;
	}
		/**
	 *
	 * @param value
	 * @return
	 */
	public static  int hexToInt(String value)
	{
		int k;
		int j = 0;
		int i = 0;
		for (k = 1; k <= value.length(); k++)
		{
			switch (value.charAt(k - 1))
			{
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					i = Integer.parseInt(String.valueOf(value.charAt(k - 1)));
					// i = int.Parse(Str[k - 1]);
					break;
				case 'A':
					i = 10;
					break;
				case 'B':
					i = 11;
					break;
				case 'C':
					i = 12;
					break;
				case 'D':
					i = 13;
					break;
				case 'E':
					i = 14;
					break;
				case 'F':
					i = 15;
					break;
				case 'a':
					i = 10;
					break;
				case 'b':
					i = 11;
					break;
				case 'c':
					i = 12;
					break;
				case 'd':
					i = 13;
					break;
				case 'e':
					i = 14;
					break;
				case 'f':
					i = 15;
					break;

			}
			j = j * 16 + i;
		}
		return j;
	}
	/**
	 * 16进制字符串转换为字符串
	 *
	 * @param s
	 * @return
	 */
	public static String hexStringToString(String s) {
		if (s == null || s.equals("")) {
			return null;
		}
		s = s.replace(" ", "");
		byte[] baKeyword = new byte[s.length() / 2];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				baKeyword[i] = (byte) (0xff & Integer.parseInt(
						s.substring(i * 2, i * 2 + 2), 16));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			s = new String(baKeyword, "gbk");
			new String();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return s;
	}


	/**
	 * 十六进制转二进制
	 *
	 * @param hex
	 * @param len
	 * @return
	 */
	public static String hexToBin(String hex, int len )
	{
		String s = Integer.toString(BitOperator.hexToInt(hex), 2);
		while (s.length() < len)
		{
			s = "0" + s;
		}
		return s;
	}
}
